package cn.kinoko.common.utils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author kinoko
 */
public class BitmapUtil {

    /**
     * 在给定的数值上设置指定位置的二进制位为1
     *
     * @param bitmask 原始数值
     * @param index 索引位（从右向左，最右边的是第0位）
     * @return 修改后的数值
     * @throws IllegalArgumentException 如果位置超出64位整数范围
     */
    public static long setBitAt(long bitmask, int... index) {
        for (long i : index) {
            if (i < 0 || i > 63) {
                throw new IllegalArgumentException("index out of range. Must be between 0 and 63.");
            }

            // 使用位运算符设置指定位置的位为1 （1 左移 position 位，然后与 number 进行按位或运算）
            bitmask |= (1L << i);
        }
        return bitmask;
    }

    /**
     * 在给定的数值上设置指定位置的二进制位为1
     *
     * @param bitmask 原始数值
     * @param index 索引位（从右向左，最右边的是第0位）
     * @return 修改后的数值
     * @throws IllegalArgumentException 如果位置超出64位整数范围
     */
    public static long setBitAt(long bitmask, List<Long> index) {
        for (long i : index) {
            if (i < 0 || i > 63) {
                throw new IllegalArgumentException("index out of range. Must be between 0 and 63.");
            }

            // 使用位运算符设置指定位置的位为1 （1 左移 position 位，然后与 number 进行按位或运算）
            bitmask |= (1L << i);
        }
        return bitmask;
    }

    /**
     * 在给定的数值上设置指定位置的二进制位为0
     *
     * @param bitmask 原始数值
     * @param index 索引位（从右向左，最右边的是第0位）
     * @return 修改后的数值
     * @throws IllegalArgumentException 如果位置超出64位整数范围
     */
    public static long clearBitAt(long bitmask, int... index) {
        for (long i : index) {
            if (i < 0 || i > 63) {
                throw new IllegalArgumentException("index out of range. Must be between 0 and 63.");
            }

            // 使用位运算符设置指定位置的位为0 （1 左移 position 位，然后与 number 进行按位异或运算）
            bitmask &= ~(1L << i);
        }
        return bitmask;
    }

    /**
     * 判断指定位置的二进制位是否为1
     *
     * @param bitmask 原始数值
     * @param index 索引位（从右向左，最右边的是第0位）
     * @return 是否为1
     * @throws IllegalArgumentException 如果位置超出64位整数范围
     */
    public static boolean isBitAt(long bitmask, int... index) {
        for (long i : index) {
            if (i < 0 || i > 63) {
                throw new IllegalArgumentException("index out of range. Must be between 0 and 63.");
            }

            // 使用位运算符判断指定位置的位是否为1 （1 左移 position 位，然后与 number 进行按位与运算）
            if ((bitmask & (1L << i)) != 0) return true;
        }
        return false;
    }

    /**
     * 获取所有1的索引
     *
     * @param bitmask 原始数值
     * @return 索引列表
     */
    public static List<Long> getAllBitAt(long bitmask) {
        if (bitmask == 0) return null;
        List<Long> result = new ArrayList<>();
        while (bitmask != 0) {
            // 使用位运算符获取最低位的1的位置
            long position = Long.numberOfTrailingZeros(bitmask);

            // 将最低位的1置为0
            bitmask &= ~(1L << position);

            // 添加到结果列表中
            result.add(position);
        }
        return result;
    }

}
